Şema Birleştirme ile GraphQL Federasyonunun gücünü keşfedin. Ölçeklenebilirliği ve sürdürülebilirliği artırarak birden çok servisten birleşik bir GraphQL API'si oluşturmayı öğrenin.
GraphQL Federasyonu: Şema Birleştirme (Schema Stitching) - Kapsamlı Bir Rehber
Sürekli gelişen modern uygulama geliştirme dünyasında, ölçeklenebilir ve sürdürülebilir mimarilere olan ihtiyaç çok önemli hale gelmiştir. Mikroservisler, doğal modülerlikleri ve bağımsız dağıtılabilirlikleri ile popüler bir çözüm olarak ortaya çıkmıştır. Ancak, çok sayıda mikroservisi yönetmek, özellikle istemci uygulamalarına birleşik bir API sunma konusunda karmaşıklıklara yol açabilir. İşte bu noktada GraphQL Federasyonu ve özellikle Şema Birleştirme (Schema Stitching) devreye giriyor.
GraphQL Federasyonu Nedir?
GraphQL Federasyonu, birden çok temel GraphQL servisinden (genellikle mikroservisleri temsil eder) tek, birleşik bir GraphQL API'si oluşturmanıza olanak tanıyan güçlü bir mimaridir. Geliştiricilerin farklı servislerdeki verileri tek bir grafmış gibi sorgulamasına olanak tanır, bu da istemci deneyimini basitleştirir ve istemci tarafında karmaşık orkestrasyon mantığına olan ihtiyacı azaltır.
GraphQL Federasyonu için iki temel yaklaşım vardır:
- Şema Birleştirme (Schema Stitching): Bu, ağ geçidi katmanında birden çok GraphQL şemasını tek, birleşik bir şemada birleştirmeyi içerir. Bu daha eski bir yaklaşımdır ve şema birleştirme ve sorgu delegasyonunu yönetmek için kütüphanelere dayanır.
- Apollo Federation: Bu, federasyon sürecini yönetmek için bildirimsel bir şema dili ve özel bir sorgu planlayıcısı kullanan daha yeni ve sağlam bir yaklaşımdır. Tür uzantıları, anahtar direktifleri ve dağıtık izleme gibi gelişmiş özellikler sunar.
Bu makale, kavramlarını, faydalarını, sınırlamalarını ve pratik uygulamasını keşfederek Şema Birleştirme (Schema Stitching) üzerine odaklanmaktadır.
Şema Birleştirmeyi Anlamak
Şema Birleştirme, birden çok GraphQL şemasını tek ve uyumlu bir şemada birleştirme işlemidir. Bu birleşik şema, temel servislerin karmaşıklığını istemciden gizleyen bir cephe (facade) görevi görür. Bir istemci birleştirilmiş şemaya bir istekte bulunduğunda, ağ geçidi isteği akıllıca uygun temel servise/servislere yönlendirir, verileri alır ve sonuçları istemciye döndürmeden önce birleştirir.
Şöyle düşünebilirsiniz: Her biri farklı mutfaklarda uzmanlaşmış birden fazla restoranınız (servisleriniz) var. Şema Birleştirme, her restorandaki tüm yemekleri birleştiren evrensel bir menü gibidir. Bir müşteri (istemci) evrensel menüden sipariş verdiğinde, sipariş akıllıca uygun restoran mutfaklarına yönlendirilir, yemek hazırlanır ve ardından müşteri için tek bir teslimatta birleştirilir.
Şema Birleştirmedeki Anahtar Kavramlar
- Uzak Şemalar (Remote Schemas): Bunlar, her bir temel servisin bireysel GraphQL şemalarıdır. Her servis, sağladığı verileri ve işlemleri tanımlayan kendi şemasını sunar.
- Ağ Geçidi (Gateway): Ağ geçidi, uzak şemaları bir araya getirmekten ve birleşik şemayı istemciye sunmaktan sorumlu merkezi bileşendir. İstemci isteklerini alır, uygun servislere yönlendirir ve sonuçları birleştirir.
- Şema Birleştirme (Schema Merging): Bu, uzak şemaları tek bir şemada birleştirme işlemidir. Bu genellikle çakışmaları önlemek için türlerin ve alanların yeniden adlandırılmasını ve farklı şemalar arasındaki türler arası ilişkilerin tanımlanmasını içerir.
- Sorgu Delegasyonu (Query Delegation): Bir istemci birleştirilmiş şemaya bir istekte bulunduğunda, ağ geçidinin verileri almak için isteği uygun temel servise/servislere delege etmesi gerekir. Bu, istemcinin sorgusunu uzak servisin anlayabileceği bir sorguya çevirmeyi içerir.
- Sonuç Toplama (Result Aggregation): Ağ geçidi, temel servislerden verileri aldıktan sonra, sonuçları istemciye döndürülebilecek tek bir yanıtta birleştirmesi gerekir. Bu genellikle verileri birleştirilmiş şemanın yapısına uyacak şekilde dönüştürmeyi içerir.
Şema Birleştirmenin Faydaları
Şema Birleştirme, mikroservis mimarisini benimseyen kuruluşlar için birçok cazip fayda sunar:
- Birleşik API: İstemciler için tek ve tutarlı bir API sağlar, veri erişimini basitleştirir ve istemcilerin doğrudan birden çok servisle etkileşim kurma ihtiyacını azaltır. Bu, daha temiz ve daha sezgisel bir geliştirici deneyimi sağlar.
- Azaltılmış İstemci Karmaşıklığı: İstemcilerin yalnızca birleşik şema ile etkileşim kurması gerekir, bu da onları temel mikroservis mimarisinin karmaşıklığından korur. Bu, istemci tarafı geliştirmeyi basitleştirir ve istemcide gereken kod miktarını azaltır.
- Artırılmış Ölçeklenebilirlik: Bireysel servisleri özel ihtiyaçlarına göre bağımsız olarak ölçeklendirmenize olanak tanır. Bu, sistemin genel ölçeklenebilirliğini ve dayanıklılığını artırır. Örneğin, yüksek yük yaşayan bir kullanıcı servisi, ürün kataloğu gibi diğer servisleri etkilemeden ölçeklendirilebilir.
- İyileştirilmiş Sürdürülebilirlik: Modülerliği ve sorumlulukların ayrılmasını teşvik ederek, bireysel servislerin bakımını ve geliştirilmesini kolaylaştırır. Bir servisteki değişikliklerin diğer servisleri etkileme olasılığı daha düşüktür.
- Aşamalı Benimseme: Adım adım uygulanabilir, bu da monolitik bir mimariden mikroservis mimarisine kademeli olarak geçiş yapmanıza olanak tanır. Mevcut API'leri bir araya getirerek başlayabilir ve ardından monoliti yavaş yavaş daha küçük servislere ayırabilirsiniz.
Şema Birleştirmenin Sınırlamaları
Şema Birleştirme çok sayıda avantaj sunsa da, sınırlamalarının farkında olmak önemlidir:
- Karmaşıklık: Şema birleştirmeyi uygulamak ve yönetmek, özellikle büyük ve karmaşık sistemlerde karmaşık olabilir. Dikkatli planlama ve tasarım esastır.
- Performans Yükü: Ağ geçidi, ekstra dolaylı katman ve sorguları delege etme ve sonuçları toplama ihtiyacı nedeniyle bir miktar performans yükü getirir. Bu yükü en aza indirmek için dikkatli optimizasyon çok önemlidir.
- Şema Çakışmaları: Farklı servislerden şemaları birleştirirken, özellikle aynı tür adlarını veya alan adlarını kullanıyorlarsa çakışmalar ortaya çıkabilir. Bu, dikkatli şema tasarımı ve potansiyel olarak türlerin ve alanların yeniden adlandırılmasını gerektirir.
- Sınırlı Gelişmiş Özellikler: Apollo Federation ile karşılaştırıldığında, Şema Birleştirme, tür uzantıları ve anahtar direktifleri gibi bazı gelişmiş özelliklerden yoksundur, bu da farklı şemalar arasındaki türler arası ilişkileri yönetmeyi daha zor hale getirebilir.
- Araç Olgunluğu: Şema Birleştirme etrafındaki araçlar ve ekosistem, Apollo Federation etrafındakiler kadar olgun değildir. Bu, sorunları ayıklamayı ve gidermeyi daha zor hale getirebilir.
Şema Birleştirmenin Pratik Uygulaması
Node.js ve graphql-tools
kütüphanesini (şema birleştirme için popüler bir seçim) kullanarak Şema Birleştirmenin nasıl uygulanacağına dair basitleştirilmiş bir örnek üzerinden geçelim. Bu örnek, iki mikroservisi içerir: bir Kullanıcı Servisi ve bir Ürün Servisi.
1. Uzak Şemaları Tanımlayın
İlk olarak, her bir uzak servis için GraphQL şemalarını tanımlayın.
Kullanıcı Servisi (user-service.js
):
const { buildSchema } = require('graphql');
const userSchema = buildSchema(`
type User {
id: ID!
name: String
email: String
}
type Query {
user(id: ID!): User
}
`);
const users = [
{ id: '1', name: 'Alice Smith', email: 'alice@example.com' },
{ id: '2', name: 'Bob Johnson', email: 'bob@example.com' },
];
const userRoot = {
user: (args) => users.find(user => user.id === args.id),
};
module.exports = {
schema: userSchema,
rootValue: userRoot,
};
Ürün Servisi (product-service.js
):
const { buildSchema } = require('graphql');
const productSchema = buildSchema(`
type Product {
id: ID!
name: String
price: Float
userId: ID! # Kullanıcı Servisine yabancı anahtar
}
type Query {
product(id: ID!): Product
}
`);
const products = [
{ id: '101', name: 'Laptop', price: 1200, userId: '1' },
{ id: '102', name: 'Smartphone', price: 800, userId: '2' },
];
const productRoot = {
product: (args) => products.find(product => product.id === args.id),
};
module.exports = {
schema: productSchema,
rootValue: productRoot,
};
2. Ağ Geçidi Servisini Oluşturun
Şimdi, iki şemayı bir araya getirecek olan ağ geçidi servisini oluşturun.
Ağ Geçidi Servisi (gateway.js
):
const { stitchSchemas } = require('@graphql-tools/stitch');
const { makeRemoteExecutableSchema } = require('@graphql-tools/wrap');
const { graphqlHTTP } = require('express-graphql');
const express = require('express');
const { introspectSchema } = require('@graphql-tools/wrap');
const { printSchema } = require('graphql');
const fetch = require('node-fetch');
async function createRemoteSchema(uri) {
const fetcher = async (params) => {
const response = await fetch(uri, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(params),
});
return response.json();
};
const schema = await introspectSchema(fetcher);
return makeRemoteExecutableSchema({
schema,
fetcher,
});
}
async function main() {
const userSchema = await createRemoteSchema('http://localhost:4001/graphql');
const productSchema = await createRemoteSchema('http://localhost:4002/graphql');
const stitchedSchema = stitchSchemas({
subschemas: [
{ schema: userSchema },
{ schema: productSchema },
],
typeDefs: `
extend type Product {
user: User
}
`,
resolvers: {
Product: {
user: {
selectionSet: `{ userId }`,
resolve(product, args, context, info) {
return info.mergeInfo.delegateToSchema({
schema: userSchema,
operation: 'query',
fieldName: 'user',
args: {
id: product.userId,
},
context,
info,
});
},
},
},
},
});
const app = express();
app.use('/graphql', graphqlHTTP({
schema: stitchedSchema,
graphiql: true,
}));
app.listen(4000, () => console.log('Ağ Geçidi sunucusu http://localhost:4000/graphql üzerinde çalışıyor'));
}
main().catch(console.error);
3. Servisleri Çalıştırın
Kullanıcı Servisini ve Ürün Servisini farklı portlarda çalıştırmanız gerekecektir. Örneğin:
Kullanıcı Servisi (port 4001):
const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const { schema, rootValue } = require('./user-service');
const app = express();
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: rootValue,
graphiql: true,
}));
app.listen(4001, () => console.log('Kullanıcı servisi http://localhost:4001/graphql üzerinde çalışıyor'));
Ürün Servisi (port 4002):
const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const { schema, rootValue } = require('./product-service');
const app = express();
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: rootValue,
graphiql: true,
}));
app.listen(4002, () => console.log('Ürün servisi http://localhost:4002/graphql üzerinde çalışıyor'));
4. Birleştirilmiş Şemayı Sorgulayın
Artık birleştirilmiş şemayı ağ geçidi üzerinden (port 4000'de çalışan) sorgulayabilirsiniz. Şunun gibi bir sorgu çalıştırabilirsiniz:
query {
product(id: "101") {
id
name
price
user {
id
name
email
}
}
}
Bu sorgu, ID'si "101" olan ürünü alır ve ayrıca ilişkili kullanıcıyı Kullanıcı Servisinden getirir, bu da Şema Birleştirmenin tek bir istekte birden çok servisteki verileri nasıl sorgulamanıza olanak tanıdığını gösterir.
Gelişmiş Şema Birleştirme Teknikleri
Temel örneğin ötesinde, Şema Birleştirme uygulamanızı geliştirmek için kullanılabilecek bazı gelişmiş teknikler şunlardır:
- Şema Delegasyonu (Schema Delegation): Bu, bir sorgunun parçalarını istenen verilere göre farklı servislere delege etmenize olanak tanır. Örneğin, bir `User` türünün çözümlenmesini Kullanıcı Servisine ve bir `Product` türünün çözümlenmesini Ürün Servisine delege edebilirsiniz.
- Şema Dönüşümü (Schema Transformation): Bu, bir uzak servisin şemasını birleşik şemaya eklenmeden önce değiştirmeyi içerir. Bu, türleri ve alanları yeniden adlandırmak, yeni alanlar eklemek veya mevcut alanları kaldırmak için yararlı olabilir.
- Özel Çözücüler (Custom Resolvers): Karmaşık veri dönüşümlerini işlemek veya birden çok servisten veri alıp tek bir sonuçta birleştirmek için ağ geçidinde özel çözücüler tanımlayabilirsiniz.
- Bağlam Paylaşımı (Context Sharing): Ağ geçidi ve uzak servisler arasında kimlik doğrulama belirteçleri veya kullanıcı kimlikleri gibi bağlam bilgilerini paylaşmak genellikle gereklidir. Bu, sorgu delegasyon sürecinin bir parçası olarak bağlam bilgilerini geçirerek başarılabilir.
- Hata Yönetimi (Error Handling): Uzak servislerde meydana gelen hataları zarif bir şekilde işlemek için sağlam bir hata yönetimi uygulayın. Bu, hataları günlüğe kaydetmeyi, kullanıcı dostu hata mesajları döndürmeyi veya başarısız istekleri yeniden denemeyi içerebilir.
Şema Birleştirme ve Apollo Federation Arasında Seçim Yapmak
Şema Birleştirme, GraphQL Federasyonu için geçerli bir seçenek olsa da, Apollo Federation gelişmiş özellikleri ve iyileştirilmiş geliştirici deneyimi nedeniyle daha popüler bir seçenek haline gelmiştir. İşte iki yaklaşımın bir karşılaştırması:
Özellik | Şema Birleştirme | Apollo Federation |
---|---|---|
Şema Tanımı | Mevcut GraphQL şema dilini kullanır | Direktiflerle bildirimsel bir şema dili kullanır |
Sorgu Planlama | Manuel sorgu delegasyonu gerektirir | Apollo Gateway tarafından otomatik sorgu planlama |
Tür Uzantıları | Sınırlı destek | Tür uzantıları için yerleşik destek |
Anahtar Direktifleri | Desteklenmiyor | Varlıkları tanımlamak için @key direktifini kullanır |
Dağıtık İzleme | Manuel uygulama gerektirir | Dağıtık izleme için yerleşik destek |
Araçlar ve Ekosistem | Daha az olgun araçlar | Daha olgun araçlar ve geniş bir topluluk |
Karmaşıklık | Büyük sistemlerde yönetimi karmaşık olabilir | Büyük ve karmaşık sistemler için tasarlanmıştır |
Ne Zaman Şema Birleştirme Seçilmeli:
- Mevcut GraphQL servisleriniz var ve bunları hızla birleştirmek istiyorsunuz.
- Basit bir federasyon çözümüne ihtiyacınız var ve gelişmiş özellikler gerektirmiyorsunuz.
- Sınırlı kaynaklarınız var ve Apollo Federation kurmanın getireceği ek yükten kaçınmak istiyorsunuz.
Ne Zaman Apollo Federation Seçilmeli:
- Birden çok ekip ve servisle büyük ve karmaşık bir sistem inşa ediyorsunuz.
- Tür uzantıları, anahtar direktifleri ve dağıtık izleme gibi gelişmiş özelliklere ihtiyacınız var.
- Daha sağlam ve ölçeklenebilir bir federasyon çözümü istiyorsunuz.
- Federasyona daha bildirimsel ve otomatik bir yaklaşımı tercih ediyorsunuz.
Gerçek Dünya Örnekleri ve Kullanım Durumları
İşte Şema Birleştirme de dahil olmak üzere GraphQL Federasyonunun nasıl kullanılabileceğine dair bazı gerçek dünya örnekleri:
- E-ticaret Platformu: Bir e-ticaret platformu, bir ürün kataloğu servisi, bir kullanıcı servisi, bir sipariş servisi ve bir ödeme servisi gibi birden çok servisten gelen verileri birleştirmek için GraphQL Federasyonunu kullanabilir. Bu, istemcilerin ürün ayrıntılarını, kullanıcı profillerini, sipariş geçmişini ve ödeme bilgilerini görüntülemek için ihtiyaç duydukları tüm bilgileri kolayca almalarını sağlar.
- Sosyal Medya Platformu: Bir sosyal medya platformu, kullanıcı profillerini, gönderileri, yorumları ve beğenileri yöneten servislerden gelen verileri birleştirmek için GraphQL Federasyonunu kullanabilir. Bu, istemcilerin bir kullanıcının profilini, gönderilerini ve bu gönderilerle ilişkili yorumları ve beğenileri görüntülemek için gereken tüm bilgileri verimli bir şekilde almasını sağlar.
- Finansal Hizmetler Uygulaması: Bir finansal hizmetler uygulaması, hesapları, işlemleri ve yatırımları yöneten servislerden gelen verileri birleştirmek için GraphQL Federasyonunu kullanabilir. Bu, istemcilerin hesap bakiyelerini, işlem geçmişini ve yatırım portföylerini görüntülemek için ihtiyaç duydukları tüm bilgileri kolayca almalarını sağlar.
- İçerik Yönetim Sistemi (CMS): Bir CMS, makaleler, resimler, videolar ve kullanıcı tarafından oluşturulan içerik gibi çeşitli kaynaklardan gelen verileri entegre etmek için GraphQL Federasyonundan yararlanabilir. Bu, belirli bir konu veya yazarla ilgili tüm içeriği almak için birleşik bir API sağlar.
- Sağlık Uygulaması: Elektronik sağlık kayıtları (EHR), laboratuvar sonuçları ve randevu planlaması gibi farklı sistemlerden hasta verilerini entegre edin. Bu, doktorlara kapsamlı hasta bilgilerine tek bir erişim noktası sunar.
Şema Birleştirme İçin En İyi Uygulamalar
Başarılı bir Şema Birleştirme uygulaması sağlamak için şu en iyi uygulamaları izleyin:
- Şemanızı Dikkatlice Planlayın: Şemaları bir araya getirmeye başlamadan önce, birleşik şemanın yapısını dikkatlice planlayın. Bu, farklı şemalar arasındaki türler arası ilişkileri tanımlamayı, çakışmaları önlemek için türleri ve alanları yeniden adlandırmayı ve genel veri erişim modellerini dikkate almayı içerir.
- Tutarlı Adlandırma Kuralları Kullanın: Tüm servislerde türler, alanlar ve işlemler için tutarlı adlandırma kuralları benimseyin. Bu, çakışmaları önlemeye ve birleşik şemanın anlaşılmasını kolaylaştırmaya yardımcı olacaktır.
- Şemanızı Belgeleyin: Türlerin, alanların ve işlemlerin açıklamaları da dahil olmak üzere birleşik şemayı ayrıntılı olarak belgeleyin. Bu, geliştiricilerin şemayı anlamasını ve kullanmasını kolaylaştıracaktır.
- Performansı İzleyin: Herhangi bir performans darboğazını belirlemek ve gidermek için ağ geçidinin ve uzak servislerin performansını izleyin. İstekleri birden çok serviste izlemek için dağıtık izleme gibi araçlar kullanın.
- Güvenliği Uygulayın: Ağ geçidini ve uzak servisleri yetkisiz erişime karşı korumak için uygun güvenlik önlemlerini uygulayın. Bu, kimlik doğrulama ve yetkilendirme mekanizmalarının yanı sıra girdi doğrulama ve çıktı kodlamasını kullanmayı içerebilir.
- Şemanızı Sürümleyin: Şemalarınızı geliştirdikçe, istemcilerin şemanın eski sürümlerini bozulmadan kullanmaya devam edebilmelerini sağlamak için bunları uygun şekilde sürümleyin. Bu, kırılgan değişiklikleri önlemeye ve geriye dönük uyumluluğu sağlamaya yardımcı olacaktır.
- Dağıtımı Otomatikleştirin: Değişikliklerin hızlı ve güvenilir bir şekilde dağıtılabilmesini sağlamak için ağ geçidinin ve uzak servislerin dağıtımını otomatikleştirin. Bu, hata riskini azaltmaya ve sistemin genel çevikliğini artırmaya yardımcı olacaktır.
Sonuç
Şema Birleştirme ile GraphQL Federasyonu, bir mikroservis mimarisinde birden çok servisten birleşik API'ler oluşturmak için güçlü bir yaklaşım sunar. Temel kavramlarını, faydalarını, sınırlamalarını ve uygulama tekniklerini anlayarak, veri erişimini basitleştirmek, ölçeklenebilirliği artırmak ve sürdürülebilirliği geliştirmek için Şema Birleştirmeden yararlanabilirsiniz. Apollo Federation daha gelişmiş bir çözüm olarak ortaya çıkmış olsa da, Şema Birleştirme daha basit senaryolar veya mevcut GraphQL servislerini entegre ederken geçerli bir seçenek olmaya devam etmektedir. Kuruluşunuz için en iyi yaklaşımı seçmek üzere özel ihtiyaçlarınızı ve gereksinimlerinizi dikkatlice değerlendirin.